package cn.com.greatwall.flowable.service.impl;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.ObjectUtils;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.greatwall.common.exception.EntityExistException;
import cn.com.greatwall.common.utils.PageUtil;
import cn.com.greatwall.flowable.service.ModelService;
import cn.com.greatwall.flowable.service.dto.ModelDto;
import cn.com.greatwall.flowable.service.dto.criteria.ModelQueryCriteria;
import cn.com.greatwall.flowable.service.mapstruct.ModelMapper;
import lombok.RequiredArgsConstructor;

/**
 * @Author herw
 * @Time 2020-11-16 09:49:28
 * @Version 1.0
 * @Description: TODO(用一句话描述该文件做什么)
 */
@Service
@RequiredArgsConstructor
public class ModelServiceImpl implements ModelService {
    private final RepositoryService repositoryService;
    private final ModelMapper modelMapper;

    @Override
    public Map<String, Object> queryAll(ModelQueryCriteria criteria, Pageable pageable) {
        ModelQuery query = repositoryService.createModelQuery();
        if (ObjectUtils.isNotEmpty(criteria.getId())) {
            query.modelId(criteria.getId());
        }
        if (ObjectUtils.isNotEmpty(criteria.getCategory())) {
            query.modelCategoryLike("%" + criteria.getCategory() + "%");
        }
        if (ObjectUtils.isNotEmpty(criteria.getName())) {
            query.modelNameLike("%" + criteria.getName() + "%");
        }
        if (ObjectUtils.isNotEmpty(criteria.getKey())) {
            query.modelKey(criteria.getKey());
        }
        if (ObjectUtils.isNotEmpty(criteria.getVersion())) {
            query.modelVersion(Integer.parseInt(criteria.getVersion()));
        }
        if (ObjectUtils.isNotEmpty(criteria.getLatestVersion())) {
            boolean isLatestVersion = Boolean.parseBoolean(criteria.getLatestVersion());
            if (isLatestVersion) {
                query.latestVersion();
            }
        }
        if (ObjectUtils.isNotEmpty(criteria.getDeployed())) {
            boolean isDeployed = Boolean.parseBoolean(criteria.getDeployed());
            if (isDeployed) {
                query.deployed();
            } else {
                query.notDeployed();
            }
        }
        if (ObjectUtils.isNotEmpty(criteria.getTenantId())) {
            query.modelTenantId(criteria.getTenantId());
        }

        List<Model> list = query.listPage((int) pageable.getOffset(), pageable.getPageSize());

        return PageUtil.toPage(modelMapper.toDto(list), query.count());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ModelDto findById(String id) throws UnsupportedEncodingException {
        ModelDto dto = new ModelDto();
        Model model = repositoryService.getModel(id);
//        ValidationUtil.isNull(model.getId(), "Model", "id", id);
        if (model == null) {
            throw new FlowableObjectNotFoundException("No model found with id " + id);
        }
        dto = modelMapper.toDto(model);
        if(model.hasEditorSource()) {
            byte[] editorBytes = repositoryService.getModelEditorSource(model.getId());
            dto.setEditor(new String(editorBytes,"UTF-8"));
        }
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(ModelDto resources) {
        if (repositoryService.createModelQuery().modelKey(resources.getKey()).count() > 0) {
            throw new EntityExistException(Model.class, "key", resources.getKey());
        }

        Model model = repositoryService.newModel();
        model.setKey(resources.getKey());
        model.setName(resources.getName());
        model.setVersion(1);
        model.setMetaInfo(resources.getMetaInfo());
        model.setTenantId(resources.getTenantId());
        model.setCategory(resources.getCategory());

        repositoryService.saveModel(model);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ModelDto resources) {
        Model model = repositoryService.getModel(resources.getId());
//        ValidationUtil.isNull(model.getId(), "Model", "id", resources.getId());
        if (model == null) {
            throw new FlowableObjectNotFoundException("No model found with id " + resources.getId());
        }
        model.setKey(resources.getKey());
        model.setName(resources.getName());
        model.setVersion(1);
        model.setMetaInfo(resources.getMetaInfo());
        model.setTenantId(resources.getTenantId());
        model.setCategory(resources.getCategory());

        repositoryService.saveModel(model);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<String> ids) {
        for (String id : ids) {
            repositoryService.deleteModel(id);
        }
    }
}
